package com.css.bjdt_core.validation.service;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;

import org.nutz.dao.Dao;
import org.nutz.dao.Sqls;
import org.nutz.dao.sql.Sql;
import org.nutz.dao.sql.SqlCallback;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.css.bjdt_core.cell.entity.Cell;
import com.css.bjdt_core.cell.service.CellDataService;
import com.css.bjdt_core.cell.service.CellService;
import com.css.bjdt_core.explain.entity.RptTemplateExplain;
import com.css.bjdt_core.explain.service.ReportTemplateExplainService;
import com.css.bjdt_core.report.entity.RptTemplate;
import com.css.bjdt_core.report.service.ReportTemplateManageService;
import com.css.bjdt_core.reportPrepare.entity.RptBatchTemplateRel;
import com.css.bjdt_core.reportPrepare.service.RptDealWithService;
import com.css.bjdt_core.util.CommonUtil;
import com.css.bjdt_core.util.ExecutorPool;
import com.css.bjdt_core.util.ReportConstant;
import com.css.bjdt_core.validation.entity.ValidationInfo;

@Service
public class ReportExplainValidationService {

	@Autowired
	private Dao dao;

	@Autowired
	private ReportTemplateExplainService reportTemplateExplainService;

	@Autowired
	private CellDataService cellDataService;

	@Autowired
	private RptDealWithService rptDealWithService;

	@Autowired
	private ReportTemplateManageService reportTemplateManageService;

	@Autowired
	private ValidationInfoService validationInfoService;

	@Autowired
	private ReportCommentValidateService reportCommentValidateService;

	@Autowired
	private ValidationInfoService validationInfoSvc;

	@Autowired
	private CellService cellService;

	public List<ValidationInfo> validationReportExplain(String annualId, String templateId, String dzzId,
			String batchId, String unitType) {
		List<RptTemplateExplain> rptTemplateExplainList = reportTemplateExplainService
				.getAllRptTemplateExplainByTemplateIdNeedValidation(templateId);
		RptTemplate rptTemplate = reportTemplateManageService.getAnRptTemplate(templateId);
		List<ValidationInfo> validationInfoList = new ArrayList<ValidationInfo>();
		Map<String, Cell> cellMap = null;
		Map<String, String> cellValues = null;
		Map<String, Integer> tiaoMuMap = null;
		Map<String, Integer> shuziWenbenMap = null;
		List<String> explainIds = new ArrayList<>();
		if (!rptTemplateExplainList.isEmpty()) {
			for (RptTemplateExplain explain : rptTemplateExplainList) {
				explainIds.add(explain.getId());
			}
			cellValues = cellDataService.getCellValuesForColRow(annualId, templateId, dzzId, unitType);
			cellMap = new HashMap<>();
			List<Cell> cells = cellService.getCellStrategyByTemplateId(templateId);
			for (Cell cell : cells) {
				cellMap.put(cell.getAbsRowNum() + "_" + cell.getAbsColNum(), cell);
			}
			tiaoMuMap = getTiaoMuCountMap(annualId, dzzId, explainIds);
			shuziWenbenMap = getShuziWenbenCountMap(annualId, dzzId, explainIds);
		}
		for (RptTemplateExplain rptTemplateExplain : rptTemplateExplainList) {
			String key = rptTemplateExplain.getTemplateRow() + "_" + rptTemplateExplain.getTemplateCol();
			String cellValue = cellValues.get(key);
			cellValue = cellValue == null ? "0" : cellValue;
			Cell cell = cellMap.get(key);
			String cellExp = "";
			if (cell == null || null == cell.getRelColNum() || ("").equals(cell.getRelColNum())) {
				cellExp = rptTemplate.getName();
			} else {
				cellExp = rptTemplate.getName() + "(" + CommonUtil.numToLetter(cell.getAbsColNum() + "")
						+ cell.getAbsRowNum() + ")";
			}
			if (rptTemplateExplain.getExplainType().equals("1")) {
				Integer num = tiaoMuMap.get(rptTemplateExplain.getId());
				String explainNum = num == null ? "0" : num + "";
				if ((!"0".equals(explainNum) && cellValue.equals("0"))
						|| ("0".equals(explainNum) && !cellValue.equals("0"))) {
					ValidationInfo validationInfo = new ValidationInfo();
					validationInfo.setId(CommonUtil.getUUID());
					validationInfo.setBatchId(batchId);
					validationInfo.setSourceExp(rptTemplateExplain.getId());
					validationInfo.setCellExp(cellExp);
					validationInfo.setActualExp(cellExp + "中的值为" + cellValue + ",而‘"
							+ rptTemplateExplain.getTemplateExplainName() + "’与报表中的值不符");
					validationInfo.setValidationType("6");
					validationInfo.setValidationState("2");
					validationInfo.setCellId("");
					validationInfo.setDzzId(dzzId);
					validationInfo.setTemplateId(templateId);
					validationInfoList.add(validationInfo);
				}
			} else {
				Integer num = shuziWenbenMap.get(rptTemplateExplain.getId());
				String explainNum = num == null ? "0" : num + "";
				if (("0").equals(explainNum) && !cellValue.equals("0")) {
					ValidationInfo validationInfo = new ValidationInfo();
					validationInfo.setId(CommonUtil.getUUID());
					validationInfo.setBatchId(batchId);
					validationInfo.setSourceExp(rptTemplateExplain.getId());
					validationInfo.setCellExp(cellExp);
					validationInfo.setActualExp(cellExp + "中的值为" + cellValue + ",而‘"
							+ rptTemplateExplain.getTemplateExplainName() + "’没有记录");
					validationInfo.setValidationType("6");
					validationInfo.setValidationState("2");
					validationInfo.setCellId("");
					validationInfo.setDzzId(dzzId);
					validationInfo.setTemplateId(templateId);
					validationInfoList.add(validationInfo);
				}
			}
		}
		//validationInfoService.batchInsertValidationInfo(annualId, validationInfoList);
		return validationInfoList;
	}

	public Map<String, Integer> getTiaoMuCountMap(String annualId, String dzzId, List<String> explainIds) {
		String tableName = ReportConstant.EXPLAIN_TABLE_PREFIX + annualId;
		String sqlStr = "select count(DISTINCT t.ABS_ROW_NUM) count, t.explain_id from $tableName "
				+ " t where  t.dzz_id = @dzzId and t.explain_id in ( $explainIds ) GROUP BY t.explain_id ";
		Sql sql = Sqls.create(sqlStr);
		sql.params().set("dzzId", dzzId);
		sql.vars().set("tableName", tableName);
		sql.vars().set("explainIds", CommonUtil.convertIDList(explainIds));
		sql.setCallback(new SqlCallback() {
			@Override
			public Object invoke(Connection conn, ResultSet rs, Sql sql) throws SQLException {
				Map<String, Integer> res = new HashMap<>();
				while (rs.next()) {
					res.put(rs.getString("explain_id"), rs.getInt("count"));
				}
				return res;
			}
		});
		dao.execute(sql);
		return sql.getObject(Map.class);
	}

	public Map<String, Integer> getShuziWenbenCountMap(String annualId, String dzzId, List<String> explainIds) {
		String tableName = ReportConstant.EXPLAIN_TABLE_PREFIX + annualId;
		String sqlStr = "select count(1) count, t.explain_id from  $tableName t "
				+ " where t.dzz_id = @dzzId and t.explain_id in ( $explainIds ) GROUP BY t.explain_id ";
		Sql sql = Sqls.create(sqlStr);
		sql.params().set("dzzId", dzzId);
		sql.vars().set("tableName", tableName);
		sql.vars().set("explainIds", CommonUtil.convertIDList(explainIds));
		sql.setCallback(new SqlCallback() {
			@Override
			public Object invoke(Connection conn, ResultSet rs, Sql sql) throws SQLException {
				Map<String, Integer> res = new HashMap<>();
				while (rs.next()) {
					res.put(rs.getString("explain_id"), rs.getInt("count"));
				}
				return res;
			}
		});
		dao.execute(sql);
		return sql.getObject(Map.class);

	}

	//得到一张报表的报表说明和报表批注的校核条数
	public String submitInformationValidationCount(String anunalId, String templateId, String dzzId) {
		//拼表名
		String tableName = ReportConstant.VALIDATION_TABLE_PREFIX + anunalId;
		String strSql = "select count(1) from " + tableName
				+ " where DZZ_ID = @dzzId and VALIDATION_TYPE in ('5','6') and VALIDATION_STATE = '2' and TEMPLATE_ID = @templateId";
		Sql sql = Sqls.create(strSql);
		sql.params().set("dzzId", dzzId).set("templateId", templateId);
		sql.setCallback(Sqls.callback.integer());
		dao.execute(sql);
		return sql.getObject(Integer.class) + "";
	}

	//报表说明校核新方法
	public void validationReportExplainMethod(List<RptBatchTemplateRel> rptBatchTemplateRelList, String annualId,
			String dzzId, String batchId, String unitType) {
		ExecutorService pool = ExecutorPool.getInstance().getPool();
		List<ValidationInfo> validations = new ArrayList<ValidationInfo>();
		List<ReportExplainValidateTread> tasks = new ArrayList<ReportExplainValidateTread>();
		for (RptBatchTemplateRel rptBatchTemplateRel : rptBatchTemplateRelList) {
			ReportExplainValidateTread reportExplainValidateTread = new ReportExplainValidateTread(rptBatchTemplateRel,
					annualId, dzzId, batchId, unitType);
			tasks.add(reportExplainValidateTread);
		}
		try {
			List<Future<List<ValidationInfo>>> resList = pool.invokeAll(tasks);
			for (Future<List<ValidationInfo>> fu : resList) {
				if (fu.get() != null && fu.get().size() != 0) {
					validations.addAll(fu.get());
				}
			}
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ExecutionException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		validationInfoSvc.batchInsertValidationInfo(annualId, validations);
	}

	class ReportExplainValidateTread implements Callable<List<ValidationInfo>> {

		public RptBatchTemplateRel rptBatchTemplateRel;
		public String annualId;
		public String dzzId;
		public String batchId;
		public String unitType;

		public ReportExplainValidateTread(RptBatchTemplateRel rptBatchTemplateRel, String annualId, String dzzId,
				String batchId, String unitType) {
			this.rptBatchTemplateRel = rptBatchTemplateRel;
			this.annualId = annualId;
			this.dzzId = dzzId;
			this.batchId = batchId;
			this.unitType = unitType;
		}

		@Override
		public List<ValidationInfo> call() throws Exception {
			// TODO Auto-generated method stub
			List<ValidationInfo> validationInfoListInsert = new ArrayList<ValidationInfo>();
			//先做报表说明校核
			List<ValidationInfo> validationInfoListA = validationReportExplain(annualId,
					rptBatchTemplateRel.getTemplateId(), dzzId, batchId, unitType);

			//再做报表批注的校核
			List<ValidationInfo> validationInfoListB = reportCommentValidateService.insertReportCommentValidation(
					annualId, rptBatchTemplateRel.getTemplateId(), dzzId, batchId, unitType);
			validationInfoListInsert.addAll(validationInfoListA);
			validationInfoListInsert.addAll(validationInfoListB);
			return validationInfoListInsert;
		}
	}

	public String getTiaoMuCountAExplain(String annualId, String dzzId, String explainId) {
		String tableName = ReportConstant.EXPLAIN_TABLE_PREFIX + annualId;
		String sqlStr = "select count(DISTINCT t.ABS_ROW_NUM) count from $tableName "
				+ " t where  t.dzz_id = @dzzId and t.explain_id = @explainId and t.ABS_ROW_NUM != 2 and t.explain_cell_value is not null";
		Sql sql = Sqls.create(sqlStr);
		sql.params().set("dzzId", dzzId).set("explainId", explainId);
		sql.vars().set("tableName", tableName);
		sql.setCallback(Sqls.callback.str());
		dao.execute(sql);
		return sql.getObject(String.class);
	}

	public String getShuziWenbenAExplain(String annualId, String dzzId, String explainId) {
		String tableName = ReportConstant.EXPLAIN_TABLE_PREFIX + annualId;
		String sqlStr = "select count(1) count from  $tableName t "
				+ " where t.dzz_id = @dzzId and t.explain_cell_value is not null and t.explain_id = @explainId";
		Sql sql = Sqls.create(sqlStr);
		sql.params().set("dzzId", dzzId).set("explainId", explainId);
		sql.vars().set("tableName", tableName);
		sql.setCallback(Sqls.callback.str());
		dao.execute(sql);
		return sql.getObject(String.class);
	}
}
